﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Open_MUD.Kernel.Server.Services;
using Open_MUD.Kernel.Utils;
using System.Text.RegularExpressions;

namespace Open_MUD.Kernel.Interface.Client.Wizards
{
    class LoginWizard:WizardBase
    {
        const string NEW = "new";
        String msgError = "";
        String user;
        String pass1;
        String pass2;
        bool createNew = false;
        int intentos = 3;
        String[] pjs = null;
        
        public LoginWizard(Cliente c, String name,String user)
            : base(c, name)
        {
            this.user = user;
        }

        private bool validarInicio(String line)
        {
            if (line.Equals(NEW))
            {
                if (user.Equals(NEW))
                {
                    msgError = "Para crear un usuario hay que elegir un correo electrónico primero.";
                    return !base.validar(""); // el validar devuelve "error"
                }
                //Crear usuario... se finaliza la validación
                return base.validar("");
            }
            else if (! Util.getInstance().EmailCorrecto(line))
            {
                msgError = "El usuario no es una dirección de correo electrónico válida. %^ret%^Por favor Introduce tu usuario:"; // preparamos el msg que se mostrará
                return !base.validar(""); // el validar devuelve "error"
            }
            if (AuthenticationService.getInstance().existUser(line))
            { //El pj existe
                user = line;
                return base.validar(""); // el validar devuelve "todo ok"
            }
            else
            {
                msgError = "El usuario no existe.%^ret%^Introduzca '" + NEW + "' para crearlo o el correo de tu cuenta de usuario"; // preparamos el msg que se mostrará
                return !base.validar(""); // el validar devuelve "error"
            }
        }

        internal override void processLine(string key, string line)
        {
            if (estadoActual.Equals(INICIO))
            {
                if (line.Equals(NEW))
                    createNew = true;
            }else
            if (estadoActual.Equals("confirmarpassword"))
            {
                pass2 = Util.getInstance().GetMD5Hash(line);
            }else
            if ( estadoActual.Equals("loadpj") )
            {
                if (key.Equals("nuevo"))
                {
                    string[] words = line.Split(' ');
                    if (words.Length == 2)
                    {
                        if (!AuthenticationService.getInstance().existePj(words[1]))
                            AuthenticationService.getInstance().createPj(words[1],user);
                        else
                            throw new MudException("Ese nombre de personaje ya existe");
                    }
                    else
                    {
                        throw new MudException("Nombre de personaje no válido");
                    }
                }
                else
                {
                    cliente.loadPJ(line);
                    cliente.render(cliente.PJ.ficha());
                }
            }
        }

        private bool validarPassword(String line)
        {
            if (intentos <= 0)
            {
                cliente.render("Lo sentimos inténtelo más tarde");
                //TODO: Lock de 1 minuto a la IP
                cliente.Exit("LoginWizard:validarPassword");
            }
            if (AuthenticationService.getInstance().login(user, line)) // line es password, comprobamos los credenciales para entrar
            {
                return base.validar("");
            }
            else
            {
                msgError = "Login Incorrecto. Tienes " + intentos + " intentos más.%^ret%^Introduce la password:";
                intentos--;
                if (intentos == 0)
                {
                    //TODO: Registrarlo y auditarlo.
                    //TODO: Bloquear login momentaneamente.
                }
                return !base.validar("");
            }
        }

        internal bool validarPjNew(String line)
        {
            if (line.StartsWith("nuevo "))
            {
                string pj = line.Substring(5).Trim().ToLower();
                if (!AuthenticationService.getInstance().existePj(pj))
                {
                    return base.validar("");
                }
            }

            return !base.validar("");
        }
        
        internal bool validarPj(String pj)
        {
             if ( pjs != null && pjs.Contains(pj) )
                return base.validar("");
             else
                return !base.validar("");
        }
        
        internal bool ComprobarPass(String line)
        {
            if (line != null && line.Length > 3)
                return true;
            return false;
        }

        internal bool ComprobarPjNew(String line)
        {
            String[] palabras = line.Split(' ');
            if (palabras.Length == 2)
            {
                String nombrepj = palabras[1].ToLower();
                if (nombrepj.Length > 2 )
                {
                    if (!Regex.IsMatch(nombrepj, "[^a-z]")) // solo se pueden caracteres de 'a' a la 'z'
                        return true;
                }
            }
            return false;            
        }

        internal override string extractKey(string line)
        {
            if (estadoActual.Equals("menulogin") && line.IndexOf(" ") > 0)
            {
                return line.Substring(0, line.IndexOf(" "));
            }
            else if (estadoActual.Equals("loadpj") && line.StartsWith("nuevo"))
                return "nuevo";
            return base.extractKey(line);
        }
   
        internal override bool validar(string line)
        {
            if (estadoActual.Equals(INICIO))
            {
                return validarInicio(line);
            }
            else if (estadoActual.Equals("password") && createNew )
            { 
                return ComprobarPass(line);
            }           
            else if (estadoActual.Equals("password"))
            {
                return validarPassword(line);
            }
            else if (estadoActual.Equals("loadpj") && !line.StartsWith("nuevo "))
            {
                return validarPj(line);
            }
            else if (estadoActual.Equals("loadpj") && line.StartsWith("nuevo "))
            {
                return ComprobarPjNew(line);
            }
            return base.validar(line);
        }
         
        internal override bool hookValidarError(String line)
        {          
           
            if (!msgError.Equals(""))
            {
                cliente.render(msgError);
                msgError = ""; // reseteamos la variable cuando mostramos el msg
                return !base.hookValidarError(line); //avoid tratamiento por defecto
            }                

            return base.hookValidarError(line);
        }

        internal override void extraDesc(String line)
        {

            if (estadoActual.Equals("password"))
            {
                pass1 = Util.getInstance().GetMD5Hash(line);
                pjs = AuthenticationService.getInstance().damePjs(user);
                if (pjs != null && pjs.Length > 0)
                {
                    cliente.render(Util.getInstance().formatList(pjs));
                }
                else
                {
                    cliente.render("No tienes personajes creados");
                }
                cliente.render("Opciones Extra:%^ret%^"
                                    + "'%^bold%^nuevo <nombre>%^reset%^' para crear un nuevo personaje%^ret%^"
                                    + "'%^bold%^borrar <nombre>%^reset%^ para borrar un personaje");
            }
            return;
        }
        
        internal override void endWizard()
        {
           cliente.render("FUAAAA!!!");            
        }
        

    }
}
